package pATT.profilingAlgorithm.PersonalSearcher;
import java.io.Serializable;
import java.util.Iterator;


public class Category implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private TermVector			centroid = new TermVector();
	private TermVector			category_words;
	private String				category_id;
	private int					nro_instances = 0;

	public Category(String c, TermVector words){
		category_words = words;
		category_id=c;
	}

	public Category(String l, Cluster c, TermVector f){
		category_words=f;
		category_id=l;
		centroid = c.getCentroid();
		nro_instances = c.size();
	}

	public void addTree(Tree t){
		centroid.putAll(t.getRoot().getCentroid());
		nro_instances = nro_instances+t.getRoot().getInstancesNumber();
	}

	public void addCluster(Cluster c){
		centroid.putAll(c.getCentroid());
		nro_instances = nro_instances+c.size();
	}

	public void removeInstance(Instance i){
		centroid.removeAll(i.getVector());
		nro_instances--;
	}

	public TermVector overlappingWords(Category c){
		TermVector c1 = this.getCentroid();
		TermVector c2 = c.getCentroid();
		TermVector c_words = c.getWords();

		TermVector overlap = new TermVector();

		for (Iterator i=getWords().termIterator(); i.hasNext(); ) {
			String s = i.next().toString();
			if (c_words.contains(s)){
				double d = (c1.get(s)+c2.get(s)) / (c.getInstancesNumber()+this.getInstancesNumber());
				overlap.put(s,d);
			}
		}
		return overlap;
	}

	public Category(Category c1, Category c2,String l){
		TermVector overlap=c1.overlappingWords(c2);
		category_words=overlap;
		category_id=l;
		centroid.putAll(c1.getCentroid());
		centroid.putAll(c2.getCentroid());
		nro_instances = c1.getInstancesNumber()+c2.getInstancesNumber();
		c1.getWords().subtract(overlap);
		c2.getWords().subtract(overlap);
	}

	public int getInstancesNumber(){
		return nro_instances;
	}

	public TermVector getCentroid(){
		return centroid;
	}

	public TermVector getWords(){
		return category_words;
	}

	public String toString(){
		return getID()+":"+category_words.toString();
	}

	public String getID(){
		return category_id;
	}

	public double classify(Instance instance){
		double sim = category_words.compareIntersection(instance.getVector());

		if (sim >= Settings.getClassificationThreshold()){
			return sim;
		}
		else{
			return -1;
		}
	}


	public void addInstance(Instance i){
		nro_instances++;
		if (!(category_id.equals("ROOT"))){
			centroid.putAll(i.getVector());
			//update weigths
			for (Iterator ins=category_words.termIterator(); ins.hasNext(); ) {
				String s = ins.next().toString();
				category_words.remove(s);
				double d = (centroid.get(s) / getInstancesNumber());
				category_words.put(s,d);
			}
		}
	}

	public TermVector getCentroidNormalized(){
		TermVector tnew = new TermVector();
		for (Iterator i=centroid.termIterator(); i.hasNext(); ) {
			String s = i.next().toString();
			double norm_value = centroid.get(s) / (double)getInstancesNumber();
			tnew.put(s,norm_value);
		}
	    	return tnew;
	}

	public double getIntraSimilarity(){
		if (getCentroidNormalized().size()>0)
			return Math.pow(getCentroidNormalized().getLength(),2);
		else
			return 1;
	}

	//===================================================================================
	//   Para Hawk
	//===================================================================================

	public String getLabel(){
		Iterator itemIt = getWords().termIterator();
		String label = Reasoner.getBestWord((String)itemIt.next());
		while(itemIt.hasNext()){
				String thisItem = (String)itemIt.next();
				label = label + ", " + Reasoner.getBestWord(thisItem);
		}

		if (label.length()>22){
			label = label.substring(0,22);
			if (label.indexOf(",")>0)
				label = label.substring(0,label.lastIndexOf(","))+"...";
		}
		return label;
	}

	public TermVector getNoStemWords(){
		Iterator stems = getWords().termIterator();
		TermVector all_words = new TermVector();

		while(stems.hasNext()){
			String stem = (String)stems.next();
			String tv = Reasoner.getBestWord(stem);
			all_words.put(tv,1);
		}
		return all_words;
	}
}
